package top.malaoshi.data;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 封装所有列
 * 不支持修改列类型，如果修改列类型，该列数据要做转换，可能报错
 */
public class DataColumns implements Iterable<DataColumn>{
    private DataTable dataTable;
    /**
     * 存放所有列
     */
    private List<DataColumn> columnList;

    protected DataColumns(DataTable dataTable) {
        this.dataTable = dataTable;
        columnList =new ArrayList<>();
    }

    /**
     *
     * @param columnNum 列数
     */
    protected DataColumns(DataTable dataTable,int columnNum){
        this.dataTable = dataTable;
        columnList =new ArrayList<>(columnNum);
    }
    /**
     * 添加列
     * @param columnName 列名
     */
    public void add(String columnName){
        add(columnName, DataColumn.Type.UNDEFINED);
    }
    /**
     * 添加列
     * @param columnName 列名
     * @param type 列类型
     */
    public void add(String columnName, DataColumn.Type type){
        // 如果存在列就抛错
        int index = exist(columnName);
        if(index>=0){
            throw new DuplicateNameException(columnName);
        }

        DataColumn dc = new DataColumn(columnName,type);
        columnList.add(dc);

        // 添加该列数据
        for(int i = 0,count = dataTable.rows().count() ; i<count;i++){
            DataRow dataRow = dataTable.rows().get(i);
            dataRow.dataList.add(null);
        }
    }

    /**
     * 根据列名获取列索引
     * @param name
     * @return
     */
    public int getIndex(String name){
        int index = exist(name);
        if(index==-1) {
            throw new DataColumnNotFoundException(name);
        }else {
            return index;
        }
    }

    /**
     * 是否存在列
     * @param name
     * @return 如果存在该列，返回列的索引，不存在返回-1
     */
    public int exist(String name){
        for(int i = 0, size = columnList.size(); i < size; i++){
            DataColumn item = columnList.get(i);
            if(item.getName().equals(name)){
                return i;
            }
        }
        return -1;
    }
    /**
     * 返回所有列名
     * @return
     */
    public String[] getNames() {
        String[] array=new String[columnList.size()];
        for(int i = 0,length = array.length ; i < length ; i++){
            array[i] = columnList.get(i).getName();
        }
        return array;
    }

    /**
     * 废弃，此方法会暴露 columns 对象，可能会被直接修改，导致错误
     * 返回 columns ，所有的列对象
     * @return
     */
//    public List<DataColumn> getList(){
//        return columns;
//    }

    /**
     * 获取总共的列数
     * @return
     */
    public int count(){
        return columnList.size();
    }
    /**
     * 根据列索引获取 DataColumn
     * @param columnIndex
     * @return
     */
    public DataColumn get(int columnIndex){
        if(columnIndex >= count()){
            throw new DataColumnNotFoundException(columnIndex);
        }
        return columnList.get(columnIndex);
    }
    /**
     * 根据列名获取 DataColumn
     * @param columnName
     * @return
     */
    public DataColumn get(String columnName){
        return columnList.get( getIndex(columnName) );
    }


    /**
     * 删除列
     * @param columnName
     */
    public void remove(String columnName){
        int columnIndex = getIndex(columnName);
        columnList.remove(columnIndex);

        // 删除该列数据
        for(int i = 0,count = dataTable.rows().count() ; i<count;i++){
            DataRow dataRow = dataTable.rows().get(i);
            dataRow.dataList.remove(columnIndex);
        }
    }
    @Override
    public String toString() {
        return "DataColumns{" +
                "columns=" + columnList +
                '}';
    }

    @Override
    public Iterator<DataColumn> iterator() {
        return new It();
    }

    private class It implements Iterator {
        /**
         * 初始位置
         */
        private int pos = -1;
        @Override
        public boolean hasNext() {
            // 下一个位置，小于数组长度，就认为有下一个
            return pos + 1 < columnList.size();
        }
        @Override
        public DataColumn next() {
            // 取下一个值
            ++pos;
            DataColumn ret = columnList.get(pos);
            return ret;
        }
    }
}
